﻿using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;

namespace Beeflys.Generator
{
    class UStruct : AType
    {
        public UStruct(ITypeSymbol symbol, List<string> imports, Reflect reflect)
            : base(symbol, imports, reflect)
        {
            
        }
        
        public override TypeOptions Options
        {
            get { return TypeOptions.STRUCT; }
        }

        public string OriginalFullName { get; private set; }


        public bool IsSealed { get; private set; }
        public bool IsStatic { get; private set; }
        public bool IsAbstract { get; private set; }
        public bool IsTypeError { get; private set; }
        public bool IsTupleType { get; private set; }
        
        /// <summary>
        /// 是否是泛型类
        /// </summary>
        public bool IsGenericType { get; private set; }
        
        /// <summary>
        /// 自己本身是泛型
        /// </summary>
        public bool IsSelfGenericType { get; private set; }
        public List<IType> GenericArgument { get; private set; } = new List<IType>();
        
        public List<UInterface> Interfaces { get; private set; } = new List<UInterface>();
        public List<UInterface> AllInterfaces { get; private set; } = new List<UInterface>();

        public List<IType> Attributes { get; private set; } = new List<IType>();

        public List<UField> Fields { get; private set; } = new List<UField>();
        public List<UProperty> Propertys { get; private set; } = new List<UProperty>();
        public List<UMethod> Methods { get; private set; } = new List<UMethod>();



        protected override void Parse(ITypeSymbol symbol)
        {
            this.IsStatic = symbol.IsStatic;
            this.IsSealed = symbol.IsSealed;
            this.IsAbstract = symbol.IsAbstract;
            this.IsTupleType = symbol.IsTupleType;
            this.IsTypeError = symbol.Kind == SymbolKind.ErrorType;
            
            if (symbol is INamedTypeSymbol typeSymbol)
            {
                this.IsGenericType = typeSymbol.IsGenericType;
                this.IsSelfGenericType = false;

                if ( this.IsGenericType)
                {
                    var original = this.FullName.ToString();
                    var index = original.IndexOf("<");
                    this.OriginalFullName = original.Substring(0, index)+"<>";

                    var typeArguments = typeSymbol.TypeArguments.ToList();
                    foreach (var item in typeArguments)
                    {
                        //泛型参数单独处理
                        var utype = new UGenericType(item, this.Imports, this.reflect);
                        this.GenericArgument.Add(utype);
                    }
                }
            }
            else
            {
                this.IsSelfGenericType = true;
            }

            this.Interfaces.AddRange(CreateUInterfaceList(symbol.Interfaces));
            this.AllInterfaces.AddRange(CreateUInterfaceList(symbol.AllInterfaces));
            
            this.FieldParse(symbol);
            this.PropertyParse(symbol);
            this.MethodParse(symbol);
            this.AttributeParse(symbol);
        }
        
        private List<UInterface> CreateUInterfaceList(ImmutableArray<INamedTypeSymbol> Interfaces)
        {
            List<UInterface> list = new List<UInterface>();

            var interfaces = Interfaces.ToList();
            foreach (var item in interfaces)
            {
                list.Add((UInterface)item.AsUtype(this.Imports, this.reflect));
            }

            return list;
        }

        private void FieldParse(ITypeSymbol typeSymbol)
        {
            Console.WriteLine(typeSymbol.ContainingAssembly.Name);
            
            var members = typeSymbol.GetMembers();
            foreach (var item in members)
            {
                if (item is IFieldSymbol fieldSymbol)
                {
                    //Console.WriteLine(typeSymbol.ToString() + "_________________" + fieldSymbol.Name);
                    var field = new UField(fieldSymbol);
                    this.Fields.Add(field);
                }
            }
        }

        private void PropertyParse(ITypeSymbol typeSymbol)
        {
            var members = typeSymbol.GetMembers();
            foreach (var item in members)
            {
                if (item is IPropertySymbol propertySymbol)
                {
                    var property = new UProperty(propertySymbol);
                    this.Propertys.Add(property);
                }
            }
        }

        private void MethodParse(ITypeSymbol typeSymbol)
        {
            var members = typeSymbol.GetMembers();
            foreach (var item in members)
            {
                if (item is IMethodSymbol method)
                {
                    if (method.Name == ".ctor" || method.Name == ".cctor")
                    {
                        continue;
                    }

                    string methodFullName = method.ToString();
                    string methodName = methodFullName.Replace($"{this.FullName}.", string.Empty);
                    if (methodName.Contains(".set") || methodName.Contains(".get")) continue;

                    var methodInfo = new UMethod(method);

                    this.Methods.Add(methodInfo);
                }
            }
        }

        private void AttributeParse(ITypeSymbol typeSymbol)
        {
            //特殊处理
            var items = typeSymbol.GetAttributes();
            foreach (var item in items)
            {
                this.Attributes.Add(new UClass(item.AttributeClass, this.Imports, this.reflect));
            }
        }
    }
}